const { Application, MapService, User, SystemLog } = require('../models');
const { AppError } = require('../middlewares/errorHandler');
const { logger } = require('../utils/logger');

class ApplicationController {
  /**
   * 创建应用
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async createApplication(ctx) {
    const { name, type, version, config, description, releaseNotes, downloadUrl } = ctx.request.body;
    const userId = ctx.state.user.id;

    // Check if application already exists
    const existingApp = await Application.findOne({ where: { name } });
    if (existingApp) {
      throw new AppError(400, 'Application name already exists');
    }

    // Create application
    const application = await Application.create({
      name,
      type,
      version,
      config,
      description,
      releaseNotes,
      downloadUrl,
      status: 'active'
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'create_application',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Application created: ${name}`
    });

    ctx.status = 201;
    ctx.body = {
      status: 'success',
      data: { application }
    };
  }

  /**
   * 更新应用
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateApplication(ctx) {
    const { id } = ctx.params;
    const { name, type, version, config, description, releaseNotes, downloadUrl, status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const application = await Application.findByPk(id);
    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    // Update application
    await application.update({
      name,
      type,
      version,
      config,
      description,
      releaseNotes,
      downloadUrl,
      status
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_application',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Application updated: ${name}`
    });

    ctx.body = {
      status: 'success',
      data: { application }
    };
  }

  /**
   * 删除应用
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async deleteApplication(ctx) {
    const { id } = ctx.params;
    const userId = ctx.state.user.id;

    const application = await Application.findByPk(id);
    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    // Remove associated map services
    await application.setMapServices([]);
    
    await application.destroy();

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'delete_application',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Application deleted: ${application.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'Application deleted successfully'
    };
  }

  /**
   * 获取应用列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getApplications(ctx) {
    const applications = await Application.findAll({
      include: [{
        model: MapService,
        attributes: ['id', 'provider', 'status']
      }]
    });

    ctx.body = {
      status: 'success',
      data: { applications }
    };
  }

  /**
   * 获取应用
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getApplication(ctx) {
    const { id } = ctx.params;

    const application = await Application.findByPk(id, {
      include: [{
        model: MapService,
        attributes: ['id', 'provider', 'status', 'config']
      }]
    });

    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    ctx.body = {
      status: 'success',
      data: { application }
    };
  }

  /**
   * 分配地图服务
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async assignMapService(ctx) {
    const { id } = ctx.params;
    const { mapServiceId } = ctx.request.body;
    const userId = ctx.state.user.id;

    const application = await Application.findByPk(id);
    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    const mapService = await MapService.findByPk(mapServiceId);
    if (!mapService) {
      throw new AppError(404, 'Map service not found');
    }

    await application.addMapService(mapService);

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'assign_map_service',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Map service ${mapService.provider} assigned to application ${application.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'Map service assigned successfully'
    };
  }

  /**
   * 移除地图服务
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async removeMapService(ctx) {
    const { id, mapServiceId } = ctx.params;
    const userId = ctx.state.user.id;

    const application = await Application.findByPk(id);
    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    const mapService = await MapService.findByPk(mapServiceId);
    if (!mapService) {
      throw new AppError(404, 'Map service not found');
    }

    await application.removeMapService(mapService);

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'remove_map_service',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Map service ${mapService.provider} removed from application ${application.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'Map service removed successfully'
    };
  }

  /**
   * 更新应用状态
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateApplicationStatus(ctx) {
    const { id } = ctx.params;
    const { status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const application = await Application.findByPk(id);
    if (!application) {
      throw new AppError(404, 'Application not found');
    }

    await application.update({ status });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_application_status',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Application ${application.name} status updated to ${status}`
    });

    ctx.body = {
      status: 'success',
      data: { application }
    };
  }
}

module.exports = new ApplicationController(); 